/**
 * 
 */
package org.going.invoker;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.going.utils.ClassUtils;
import org.going.utils.GoingConst;
import org.going.utils.RequestUtils;

/**
 * @author ferendo.huang@gmail.com
 * 
 */
public class ArrayValueGeneratorImpl implements ParamValueGenerator, GoingConst
{

	private Map<Class<?>, PrimitiveArrayCreator> creatorMap = new HashMap<Class<?>, PrimitiveArrayCreator>();

	public ArrayValueGeneratorImpl()
	{
		super();
		creatorMap.put(byte[].class, new ByteArrayCreatorImpl());
		creatorMap.put(Byte[].class, new BytesArrayCreatorImpl());
		creatorMap.put(short[].class, new ShortArrayCreatorImpl());
		creatorMap.put(Short[].class, new ShortsArrayCreatorImpl());
		creatorMap.put(int[].class, new IntArrayCreatorImpl());
		creatorMap.put(Integer[].class, new IntegerArrayCreatorImpl());
		creatorMap.put(long[].class, new LongArrayCreatorImpl());
		creatorMap.put(Long[].class, new LongsArrayCreatorImpl());
		creatorMap.put(double[].class, new DoubleArrayCreatorImpl());
		creatorMap.put(Double[].class, new DoublesArrayCreatorImpl());
		creatorMap.put(float[].class, new FloatArrayCreatorImpl());
		creatorMap.put(Float[].class, new FloatsArrayCreatorImpl());
		creatorMap.put(boolean[].class, new BooleanArrayCreatorImpl());
		creatorMap.put(Boolean[].class, new BooleansArrayCreatorImpl());
		creatorMap.put(char[].class, new CharArrayCreatorImpl());
		creatorMap.put(Character[].class, new CharacterArrayCreatorImpl());
	}

	/**
	 * @see org.going.invoker.ParamValueGenerator#generate(int, java.lang.Class,
	 *      javax.servlet.http.HttpServletRequest)
	 */
	public Object generate(String index, Class<?> clazz, HttpServletRequest request) throws ParamValueGenerateException
	{
		String key = index + BRACKETS;
		String[] arr = request.getParameterValues(key);
		if (String.class.equals(clazz))
			return arr;
		if (ClassUtils.isPrimitiveArrayClass(clazz))
		{
			if (arr == null)
				return null;
			PrimitiveArrayCreator genericArrayCreator = creatorMap.get(clazz);
			if (genericArrayCreator != null)
				return genericArrayCreator.create(arr);
		}
		else
		{
			try
			{
				// no generic type value, there is pojo value
				Class<?> itemClass = Class.forName(clazz.getName().replace(POJOCLASS_PREFIX, EMPTY)
						.replace(POJOCLASS_END, EMPTY));
				return RequestUtils.generatePojoArray(index + BRACKET_LEFT + ZERO + BRACKET_RIGHT, itemClass, request);
			}
			catch (ClassNotFoundException e)
			{
				// do something...
				throw new ParamValueGenerateException(" Class is not found for POJO Array...", e);
			}
			catch (InstantiationException e)
			{
				throw new ParamValueGenerateException(" Can not create object for POJO Array...", e);
			}
			catch (IllegalAccessException e)
			{
				throw new ParamValueGenerateException(" Can not set property value for POJO Array...", e);
			}
		}
		throw new ParamValueGenerateException(" No value is generated for prefix :: " + key);
	}

	private interface PrimitiveArrayCreator
	{
		Object create(String[] arr);
	}

	private class ByteArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			byte[] iArr = new byte[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Byte.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class BytesArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Byte[] iArr = new Byte[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Byte.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class ShortArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			short[] iArr = new short[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Short.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class ShortsArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Short[] iArr = new Short[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Short.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class IntArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			int[] iArr = new int[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Integer.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class IntegerArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Integer[] iArr = new Integer[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Integer.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class LongArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			long[] iArr = new long[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Long.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class LongsArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Long[] iArr = new Long[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Long.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class DoubleArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			double[] iArr = new double[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Double.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class DoublesArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Double[] iArr = new Double[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Double.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class FloatArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			float[] iArr = new float[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Float.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class FloatsArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Float[] iArr = new Float[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Float.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class BooleanArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			boolean[] iArr = new boolean[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Boolean.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class BooleansArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Boolean[] iArr = new Boolean[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = Boolean.valueOf(arr[i]);
			}
			return iArr;
		}
	}

	private class CharArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			char[] iArr = new char[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = arr[i].toCharArray()[0];
			}
			return iArr;
		}
	}

	private class CharacterArrayCreatorImpl implements PrimitiveArrayCreator
	{
		@Override
		public Object create(String[] arr)
		{
			Character[] iArr = new Character[arr.length];
			for (int i = 0; i < iArr.length; i++)
			{
				iArr[i] = arr[i].toCharArray()[0];
			}
			return iArr;
		}
	}

}
